﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lacrima.Framework.Infrastructure
{
    public static class DateTimeUtils
    {
        /// <summary>
        /// 计算两个时间的时间间隔
        /// </summary>
        /// <param name="startTime">起始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <returns>时间间隔</returns>
        public static TimeSpan GetInterval(DateTime startTime, DateTime endTime)
        {
            if (startTime != null && endTime != null)
            {
                return endTime - startTime;
            }
            else
            {
                return TimeSpan.MaxValue;
            }
        }

        /// <summary>
        /// 解析目标时间的时间戳
        /// </summary>
        /// <param name="targetTime">The target time.</param>
        /// <returns>System.Double.</returns>
        public static double ParseTimeStamp(DateTime targetTime)
        {
            if (targetTime != null && targetTime >= DateTime.MinValue)
                return (targetTime.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds;
            else
                return 0d;
        }

        /// <summary>
        /// 判断当前日期是否为周末
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns><c>true</c> if [is week end] [the specified target date]; otherwise, <c>false</c>.</returns>
        public static bool IsWeekEnd(DateTime targetDate)
        {
            if (targetDate != null)
            {
                return targetDate.DayOfWeek.Equals(DayOfWeek.Sunday) || targetDate.DayOfWeek.Equals(DayOfWeek.Saturday);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 当前日期是否为休息日
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns><c>true</c> if [is off day] [the specified target date]; otherwise, <c>false</c>.</returns>
        /// <exception cref="System.ArgumentNullException">判断当前日期是否为工作日的方法：IsOffDay(DateTime targetDate)中参数不能为空;targetDate值为空请检查输入参数</exception>
        public static bool IsOffDay(DateTime targetDate)
        {
            if (targetDate != null)
            {
                if (DateTimeUtils.IsWeekEnd(targetDate))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                throw new ArgumentNullException("判断当前日期是否为工作日的方法：IsOffDay(DateTime targetDate)中参数不能为空", "targetDate值为空请检查输入参数");
            }
        }

        /// <summary>
        /// 判断目标日期是否是工作日
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns><c>true</c> if [is work day] [the specified target date]; otherwise, <c>false</c>.</returns>
        public static bool IsWorkDay(DateTime targetDate)
        {
            if (targetDate != null)
            {
                return !DateTimeUtils.IsOffDay(targetDate);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 获取目标日期所在月份第一天
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns>当月第一天</returns>
        public static DateTime FirstDayOfMonth(DateTime targetDate)
        {
            if (targetDate != null)
            {
                return new DateTime(targetDate.Year, targetDate.Month, 1);
            }
            else
            {
                throw new ArgumentNullException("获取当月第一天的方法：FirstDayOfMonth(DateTime targetDate)中参数不能为空", "targetDate值为空请检查输入参数");
            }
        }

        /// <summary>
        /// 获取目标日期所在月份下一个月的第一天
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns>下月第一天</returns>
        /// <exception cref="System.ArgumentNullException">获取当月第一天的方法中参数不能为空;targetDate值为空请检查输入参数</exception>
        public static DateTime FirstDayOfNextMonth(DateTime targetDate)
        {
            return DateTimeUtils.FirstDayOfMonth(targetDate).AddMonths(1);
        }

        /// <summary>
        ///获取目标日期所在月份最后第一天
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns>当月最后一天</returns>
        public static DateTime LastDayOfMonth(DateTime targetDate)
        {
            return DateTimeUtils.FirstDayOfNextMonth(targetDate).AddDays(-1);
        }

        /// <summary>
        /// 获取指定日期所在月份工作日集合
        /// </summary>
        /// <param name="targetDate">目标日期</param>
        /// <returns>工作日集合</returns>
        public static ISet<DateTime> GetMonthWorkDays(DateTime targetDate)
        {
            if (targetDate != null)
            {
                ISet<DateTime> workDays= new SortedSet<DateTime>();
                DateTime firstDay = DateTimeUtils.FirstDayOfMonth(targetDate);
                DateTime firstDayOfNextMonth = DateTimeUtils.FirstDayOfNextMonth(targetDate);
                while(firstDay < firstDayOfNextMonth)
                {
                    if (DateTimeUtils.IsWorkDay(firstDay))
                    {
                        workDays.Add(firstDay);
                    }
                    firstDay = firstDay.AddDays(1);
                }
                return workDays;
            }
            else
            {
                return null;
            }
        }
    }
}
